//================================================
//  Company     : ICDREC
//  Project     : SG8
//  File name   : tmr3_timer_counter.v
//  Author      : Nguyễn Việt
//  Date        : August 05th 2014
//  Version     : 
//-------------------------------------------------
// Modification History
// Date: 	By: 
// - 
//=================================================
`include "D:/ICDREC/Design/TIMER 3/RLT_v3/tmr3_define.h"
module tmr3_timer_counter(
gclk_tmr3,
reset_n,
tmr3_cnt_ev,
set_tmrif,
tcon,
sca,
t3cnt,
tmr3_int,
cnt_en,
t3cnt_en,
tmr3_on
);
// clock and reset
input 			gclk_tmr3;
input 			reset_n;
//inputs
input  			tmr3_cnt_ev;
input 	[1:0]	tcon;				
input 	[5:0]  	sca;	
input 	[23:0] 	t3cnt;
input			tmr3_int;
input			tmr3_on;
input			t3cnt_en;
//output
output 			set_tmrif;
output			cnt_en;
//internal wires and registers
reg 			sync_reg0;
reg 			sync_reg1;
reg 			detect_edge;
reg 	[6:0]  	pres;
reg 	[3:0] 	posts;
reg				q1;
reg 			q2;
reg 			cnt_en;
reg 			reg0;
reg				reg2;		
wire	[1:0] 	tcon;
wire 	[5:0] 	sca;
wire 			ex;
wire 			sign_in;

wire 			pres_en;
wire 			w1;
wire			w2;
wire 			w3;
wire			over;
wire			tmr3_int;
wire			detect_tmr3_int;
wire			t_cyc_en;
wire			posts_en;
wire			pres_res;
//SYNC signal external
always @(posedge gclk_tmr3) begin
			sync_reg0 <= `DELAY tmr3_cnt_ev;
			sync_reg1 <= `DELAY sync_reg0;
			detect_edge <= `DELAY sync_reg1;
end
//
assign ex = (tcon[1] == 1'b1)?(sync_reg1 & (~detect_edge)):(~sync_reg1 & detect_edge);
assign sign_in = (tcon[0] == 1'b1) ? ex : 1'b1;
//prescaler
always @(posedge gclk_tmr3) begin
	reg2 <= `DELAY t3cnt_en;
end
assign pres_res = t3cnt_en & ~reg2;
assign t_cyc_en = sign_in & tmr3_on;
assign pres_en = (sca[1] | sca[0]) & t_cyc_en;
always @(posedge gclk_tmr3) begin
	if(reset_n == 1'b0)
		pres[6:0] <= `DELAY 7'h00;
	else
		if(pres_res)
			pres[6:0] <= `DELAY 7'h00;
		else
			if(pres_en == 1'b1)
				pres[6:0] <= `DELAY pres[6:0] + 1'b1;
			else
				pres[6:0] <= `DELAY pres[6:0];
end
//
assign w1 = pres[0] & pres[1];
assign w2 = pres[2] & pres[3] & w1;
assign w3 = pres[4] & pres[5] & pres[6] & w2;
//
always @(*) begin
	case(sca[1:0])
		 2'b00: cnt_en = t_cyc_en;
		 2'b01: cnt_en = t_cyc_en & w1;
		 2'b10: cnt_en = t_cyc_en & w2;
		 2'b11: cnt_en = t_cyc_en & w3;
		 default cnt_en = 1'b0;
	endcase
end
//overflow
assign 	over = (t3cnt == 24'hFFFFFF) & cnt_en;
//postscaler
always @(posedge gclk_tmr3) begin
	reg0 <= `DELAY tmr3_int;
end
//	
assign detect_tmr3_int = ~reg0 & tmr3_int;
assign posts_en = detect_tmr3_int | over;
always @(posedge gclk_tmr3) begin
	if(reset_n == 1'b0)
		posts[3:0] <= `DELAY 4'h0;
	else
		casez({posts_en, detect_tmr3_int, over})
				3'b11?: posts[3:0] <= `DELAY 4'h0;
				3'b101: posts[3:0] <= `DELAY posts[3:0] + 1'b1;
				default: posts[3:0] <= `DELAY posts[3:0];
		endcase
end
//
assign set_tmrif = over & (posts == sca[5:2]);
//
endmodule

	
	
	
	
	
	